import json
import sys

import execjs
import requests
from bs4 import BeautifulSoup

cyol_url = "https://hljapi.cyol.com/appassist"

# 读取加密JS
with open('aes.js', 'r', encoding='utf-8') as f:
    js_code = f.read()
ctx = execjs.compile(js_code)


def de_param(content):
    param_data = ctx.call("cyolDecrypt", content)
    return param_data


def en_param(param_data):
    content = ctx.call("cyolEncrypt", json.dumps(param_data, separators=(',', ':')))
    return content


# 封装post请求
def hlj_post(url, param_data):
    data = {
        "param": en_param(param_data)
    }
    resp = requests.post(url, data=data)
    return resp


# 字典输入
def get_dict_input(item_dict, item_type):
    if isinstance(item_dict, list):
        new_dict = {}
        for item in item_dict:
            pop_item = item.popitem()
            new_dict[pop_item[0]] = pop_item[1]
        item_dict = new_dict
    info = ""
    i = 0
    for item_id, item_name in item_dict.items():
        info += " %s:%s " % (item_id, item_name)
        i += 1
        if len(info) >= 40:
            print("\t" + info)
            info = ""
        elif len(info) < 40 and i >= len(item_dict.items()):
            print("\t" + info)
    s_item = None
    while not s_item:
        s_item_id = input("\t请输入 %s ID:" % item_type).strip()
        s_item = item_dict.get(s_item_id)
        if s_item:
            return str(s_item_id), s_item


# 登陆获取user_id
def check_mobile(mobile):
    check_mobile_url = cyol_url + "/student/check_user"
    param_data = {
        "mobile": mobile,
    }
    resp = hlj_post(check_mobile_url, param_data)
    if resp.status_code == 200:
        result = json.loads(resp.text)
        if result['code'] == 200 and result['data']:
            user_info = result['data']
            print("============ 获取用户信息成功 ============")
            print_user_info(user_info)
            return user_info["user_id"]
        elif result['code'] == 200 and not result['data']:
            regist_info = get_regist_info(mobile)
            register_url = cyol_url + "/student/register"
            param_data = {
                "province": regist_info[1][1],
                "province_code": regist_info[1][0],
                "city": regist_info[2][1],
                "city_code": regist_info[2][0],
                "district": regist_info[3][1],
                "district_code": regist_info[3][0],
                "school": regist_info[4][1],
                "grade": regist_info[5][1],
                "grade_code": regist_info[5][0],
                "squad": regist_info[6][1],
                "squad_code": regist_info[6][0],
                "name": regist_info[0],
                "mobile": mobile,
                "school_code": regist_info[4][0]
            }
            resp = hlj_post(register_url, param_data)
            result = json.loads(resp.text)
            if result['code'] == 200 and result['data']:
                user_info = result['data']
                print("============   用户注册成功   ============")
                print_user_info(user_info)
                return user_info["user_id"]
        print("============   用户注册失败   ============")
    else:
        print("============   请求出现异常   ============")
        sys.exit()
    return None


def print_user_info(user_info):
    print("\t姓名：%s" % user_info["name"])
    print("\t地址：%s %s %s" % (user_info["province"], user_info["city"], user_info["county"]))
    print("\t学校：%s" % user_info["school"])
    print("\t年级：%s" % user_info["grade"])
    print("\t中队：%s" % user_info["squad"])


# 注册信息输入
def get_regist_info(mobile):
    district_data = requests.get("https://hljaxx.cyol.com/js/district.data.json").json()
    print("============ 请先填写用户信息 ============")
    name = None
    while not name:
        name = input("\t姓名：").strip()
    provinces = district_data["100000"]
    province = get_dict_input(provinces, "省（自治区、直辖市）")
    cities = district_data[str(province[0])]
    city = get_dict_input(cities, "市（地、州、盟）")
    districts = district_data[str(city[0])]
    district = get_dict_input(districts, "市（地、州、盟）")
    school_keyword = input("\t请输入学校名关键词：").strip()
    schools = None
    while not schools:
        schools = search_school(province[1], city[1], district[1], school_keyword)
    school = get_dict_input(schools, "学校")
    grades = {"1": "一年级", "2": "二年级", "3": "三年级", "4": "四年级", "5": "五年级", "6": "六年级",
              "7": "七年级", "8": "八年级", "9": "九年级", }
    grade = get_dict_input(grades, "年级")
    squads = {"1": "一中队", "2": "二中队", "3": "三中队", "4": "四中队", "5": "五中队", "6": "六中队",
              "7": "七中队", "8": "八中队", "9": "九中队", "10": "十中队", "11": "十一中队", "12": "十二中队",
              "13": "十三中队", "14": "十四中队", "15": "十五中队", "16": "十六中队", "17": "十七中队",
              "18": "十八中队", "19": "十九中队", "20": "二十中队", "21": "二十一中队", "22": "二十二中队",
              "23": "二十三中队", "24": "二十四中队", "25": "二十五中队", "26": "二十六中队",
              "27": "二十七中队", "28": "二十八中队", "29": "二十九中队", "30": "三十中队", "31": "三十一中队",
              "32": "三十二中队", "33": "三十三中队", "34": "三十四中队", "35": "三十五中队",
              "36": "三十六中队", "37": "三十七中队", "38": "三十八中队", "39": "三十九中队", "40": "四十中队",
              "41": "四十一中队", "42": "四十二中队", "43": "四十三中队", "44": "四十四中队",
              "45": "四十五中队", "46": "四十六中队", "47": "四十七中队", "48": "四十八中队",
              "49": "四十九中队", "50": "五十中队", }
    squad = get_dict_input(squads, "中队")
    print("============ 确认用户注册信息 ============")
    print("\t姓名：%s" % name)
    print("\t地址：%s %s %s" % (province[1], city[1], district[1]))
    print("\t学校：%s" % school[1])
    print("\t年级：%s" % grade[1])
    print("\t中队：%s" % squad[1])
    print("\t请确认注册信息是否正确：")
    controls = {"1": "确认", "2": "重新输入"}
    control = get_dict_input(controls, "")
    if control[0] == "1":
        return name, province, city, district, school, grade, squad
    else:
        get_regist_info(mobile)


# 学校搜索
def search_school(province_name, city_name, district_name, keyword):
    list_school_url = cyol_url + "/common/list_school"
    param_data = {
        "province": province_name,
        "city": city_name,
        "district": district_name,
        "keyword": keyword
    }
    resp = requests.post(list_school_url, param_data)
    if resp.status_code == 200:
        school_list = json.loads(resp.text).get("data")
        if school_list:
            return school_list
        else:
            return None


# 获取课程列表
def get_course_list():
    myHZ_url = "https://hljaxx.cyol.com/sign/myHz.html"
    resp = requests.get(myHZ_url)
    bs = BeautifulSoup(resp.content.decode("utf-8"), features="html.parser")
    courses = bs.find_all("li")
    course_list = []
    course_season = {}
    for course in courses:
        data_index = course["data-index"]
        data_id = course["data-id"]
        data_qs = course["data-qs"]
        data_content = course.contents[0].string
        course_season[data_id] = course_season.get(data_id, 0) + 1
        course_list.append(data_index.split("_") + [data_id, data_qs, data_content])
    if course_list:
        print("============ 获取课程信息成功 ============")
        for season, number in course_season.items():
            print("\t%s : 共 %d 期" % (season, number))
    return course_list


# 课程学习
def send_study(user_id, courses):
    print("============  开始课程学习  ============")
    for course in courses:
        param_data = {
            "user_id": user_id,
            "season": course[0],
            "number": course[1],
            "type": 1,
            "source": 1
        }
        send_study_url = cyol_url + "/student/send_study"
        resp = hlj_post(send_study_url, param_data)
        patten = "\t%-3s\t%-3s\t%s ==> %s"
        if resp.status_code == 200:
            print(patten % (course[2], course[3], resp.json()['msg'], course[4]))
        else:
            print(patten % (course[2], course[3], resp.text, course[4]))


# 获取徽章
def set_badge(user_id, courses):
    print("============  获取课程徽章  ============")
    for course in courses:
        param_data = {
            "user_id": user_id,
            "season": course[0],
            "number": course[1],
        }
        set_badge_url = cyol_url + "/student/set_badge"
        resp = hlj_post(set_badge_url, param_data)
        patten = "\t%-3s\t%-3s\t%s ==> %s"
        if resp.status_code == 200:
            print(patten % (course[2], course[3], resp.json()['msg'], course[4]))
        else:
            print(patten % (course[2], course[3], resp.text, course[4]))


def main():
    print("============ 红领巾爱学习工具 ============")
    mobile = input("请输入手机号码：").strip()
    # 获取个人信息
    user_id = check_mobile(mobile)
    while not user_id:
        print("============ 重新获取用户信息 ============")
        user_id = check_mobile(mobile)
    if user_id:
        # 获取课程信息
        courses = get_course_list()
        # 开始学习
        send_study(user_id, courses)
        # 获取徽章
        set_badge(user_id, courses)
    print("============ 红领巾爱学习工具 ============")


if __name__ == '__main__':
    main()
